package com.heyxampis.newmantis.controller.generico.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.heyxampis.newmantis.model.Entidade;

@Repository
public class DAOAbstratoImpl<T extends Entidade, ID extends Serializable> implements DAOAbstrato<T, ID>, Serializable {
	
	private static final long serialVersionUID = -1302272736139679164L;

	private static final Log LOG = LogFactory.getLog(DAOAbstratoImpl.class);
	
	private SessionFactory factory;
	
	@SuppressWarnings("unchecked")
	public DAOAbstratoImpl(SessionFactory factory){
		this.factory = factory;
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public DAOAbstratoImpl(){
		
	}
	
	private Class<T> persistentClass;

    public Class<T> getPersistentClass() {
            return this.persistentClass;
    }

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(readOnly = true)
	public T findPorId(ID id) {
		T t = null;
		try{
			t = (T) factory.getCurrentSession().get(getPersistentClass(), id);
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return t;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional(readOnly = true)
	public List<T> listar() {
		List<T> lista = null;
		try{
			lista = (List<T>) factory.getCurrentSession().createCriteria(getPersistentClass()).list();
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return lista;
	}

	@Override
	@Transactional
	public Long save(T entity) {
		Long idRetorno = null;
		try{
			idRetorno = (Long) factory.getCurrentSession().save(entity);
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return idRetorno;
	}

	@Override
	@Transactional
	public boolean merge(T entity) {
		boolean retorno = false;
		try{
			factory.getCurrentSession().merge(entity);
			retorno = true;
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return retorno;
	}

	@Override
	@Transactional
	public boolean update(T entity) {
		boolean retorno = false;
		try{
			factory.getCurrentSession().update(entity);
			retorno = true;
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return retorno;
	}

	@Override
	@Transactional
	public boolean saveOrUpdate(T entity) {
		boolean retorno = false;
		try{
			factory.getCurrentSession().saveOrUpdate(entity);
			retorno = true;
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return retorno;
	}

	@Override
	@Transactional
	public boolean delete(T entity) {
		boolean retorno = false;
		try{
			factory.getCurrentSession().delete(entity);
			retorno = true;
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return retorno;
	}

	@Override
	@Transactional(readOnly = true)
	public Criteria criarCriteria(T entity) {
		Criteria criteria = null;
		try{
			criteria = factory.getCurrentSession().createCriteria(getPersistentClass());
		}catch(Exception e){
			LOG.error(e.getMessage(), e);
		}
		return criteria;
	}

}
